/*
 * ccType.c
 *
 *  Created on: 2012/04/24
 *      Author: guanxiaoying
 */
#include "../coredef.h"
#include "../table/table.h"
#include "cc.h"

/* 基本型の連番 */
#define	xBASE_VOID		TYPE_VOID
#define	xBASE_CHAR		TYPE_CHAR
#define	xBASE_SCHAR		TYPE_SIGNED_CHAR
#define	xBASE_UCHAR		TYPE_UNSIGNED_CHAR
#define	xBASE_SHORT		TYPE_SHORT
#define	xBASE_SSHORT	TYPE_SIGNED_SHORT
#define	xBASE_USHORT	TYPE_UNSIGNED_SHORT
#define	xBASE_INT		TYPE_INT
#define	xBASE_SINT		TYPE_SIGNED_INT
#define	xBASE_UINT		TYPE_UNSIGNED_INT
#define	xBASE_LONG		TYPE_LONG
#define	xBASE_SLONG		TYPE_SIGNED_LONG
#define	xBASE_ULONG		TYPE_UNSIGNED_LONG
#define	xBASE_LLONG		TYPE_LONG_LONG
#define	xBASE_SLLONG	TYPE_SIGNED_LONG_LONG
#define	xBASE_ULLONG	TYPE_UNSIGNED_LONG_LONG
#define	xBASE_FLOAT		TYPE_FLOAT
#define	xBASE_DOUBLE	TYPE_DOUBLE
#define	xBASE_LDOUBLE	TYPE_LONG_DOUBLE

typedef struct {
	PSZ name;
	AST  type;
}BASICTYPEINFO;
static const BASICTYPEINFO  stBasicType_v[] = {
		{ "void", TYPE_VOID },
		{ NULL, 0 }
};
static const BASICTYPEINFO  stBasicType_c[] = {
		{ "char", TYPE_CHAR },
		{ NULL, 0 }
};
static const BASICTYPEINFO  stBasicType_s[] = {
		{ "signed_char", TYPE_SIGNED_CHAR },
		{ "signed_int", TYPE_SIGNED_INT },
		{ "short", TYPE_SHORT },
		{ "signed_short", TYPE_SIGNED_SHORT },
		{ "signed_long", TYPE_SIGNED_LONG },
		{ "signed_long_long", TYPE_SIGNED_LONG_LONG },
		{ NULL, 0 }
};
static const BASICTYPEINFO  stBasicType_u[] = {
		{ "unsigned_char", TYPE_UNSIGNED_CHAR },
		{ "unsigned_int", TYPE_UNSIGNED_INT },
		{ "unsigned_short", TYPE_UNSIGNED_SHORT },
		{ "unsigned_long", TYPE_UNSIGNED_LONG },
		{ "unsigned_long_long", TYPE_UNSIGNED_LONG_LONG },
		{ NULL, 0 }
};
static const BASICTYPEINFO  stBasicType_l[] = {
		{ "long", TYPE_LONG },
		{ "long_long", TYPE_LONG_LONG },
		{ "long_double", TYPE_LONG_DOUBLE },
		{ NULL, 0 }
};
static const BASICTYPEINFO  stBasicType_f[] = {
		{ "float", TYPE_FLOAT },
		{ NULL, 0 }
};
static const BASICTYPEINFO  stBasicType_d[] = {
		{ "double", TYPE_DOUBLE },
		{ NULL, 0 }
};
static const BASICTYPEINFO  stBasicType_i[] = {
		{ "int", TYPE_INT },
		{ NULL, 0 }
};
typedef struct {
	AST astBasic;
	AST tagInfo;
	U4 size;
}TYPEINFO_COMPPOINTER_FORTREE;
typedef struct {
	AST astBasic;
	AST tagInfo;
	U4 size;
}TYPEINFO_COMPARRAY_FORTREE;
typedef struct {
	AST intType;
	U4 size;
	U2 signFlag;
}TYPEINFO_COMPBITFIELD_FORTREE;
static AST gblPointerType = 0;
static AST gblBitfieldType = 0;
/***************************************************************
 * default typeInfo:
 *  1 void
 *  2 char
 *  3 signed char
 *  4 unsigned char
 *  5 int
 *  6 signed int
 *  7 unsigned int
 *  8 short
 *  9 signed short
 *  10 unsigned short
 *  11 long
 *  12 signed long
 *  13 unsigned long
 *  14 long long
 *  15 signed long long
 *  16 unsigned longlong
 *  17 float
 *  18 double
 *  19 long double
 *  20	const void
 *  21	const char
22	const signed char
23	const  unsigned char
24	const int
25	const signed int
26	const unsigned int
27	const short
28	const signed short
29	const unsigned short
30	const long
31	const signed long
32	const unsigned long
33	const long long
34	const signed long long
35	const unsigned longlong
36	const float
37	const double
38	const  long double
39	volatile void
40	volatile char
41	volatile signed char
42	volatile  unsigned char
43	volatile int
44	volatile signed int
45	volatile unsigned int
46	volatile short
47	volatile signed short
48	volatile unsigned short
49	volatile long
50	volatile signed long
51	volatile unsigned long
52	volatile long long
53	volatile signed long long
54	volatile unsigned longlong
55	volatile float
56	volatile double
57	volatile  long double
58	volatile const void
59	volatile const char
60	volatile const signed char
61	volatile const  unsigned char
62	volatile const int
63	volatile const signed int
64	volatile const unsigned int
65	volatile const short
66	volatile const signed short
67	volatile const unsigned short
68	volatile const long
69	volatile const signed long
70	volatile const unsigned long
71	volatile const long long
72	volatile const signed long long
73	volatile const unsigned longlong
74	volatile const float
75	volatile const double
76	volatile const  long double
 */
#define BASICTYPE_NUM 19
#define ASSIGN_FLAG_BITS   0x00FF
#define COMPATIBLE_FLAG_BITS 0xFF00
static U4  flgType = 0;
static S4  ccTypeCompPointer_forTree( AST	astType, VOID* pTypeBuf ){
	TYPEINFO_COMPPOINTER_FORTREE * pst = (TYPEINFO_COMPPOINTER_FORTREE*)pTypeBuf;
	AST idx = stTypeInfoAccess.elementType.get( astType );
	U4 data;
	if( pst->astBasic > idx ){
		return 1;
	}
	if( pst->astBasic < idx ){
		return -1;
	}
	data = stTypeInfoAccess.size.get( astType );
	if( pst->size > data ){
		return 1;
	}
	if( pst->size < data ){
		return -1;
	}
	return 0;
}
static S4  ccTypeCompBitfield_forTree( AST	astType, void* pTypeBuf ){
	TYPEINFO_COMPBITFIELD_FORTREE * pst = (TYPEINFO_COMPBITFIELD_FORTREE*)pTypeBuf;
	AST idx = stTypeInfoAccess.elementType.get( astType );
	U4 data;
	if( pst->intType > idx ){
		return 1;
	}
	if( pst->intType < idx ){
		return -1;
	}
	data = stTypeInfoAccess.size.get( astType );
	if( pst->size > data ){
		return 1;
	}
	if( pst->size < data ){
		return -1;
	}
	data = stTypeInfoAccess.signFlag.get( astType );
	if( pst->signFlag > data ){
		return 1;
	}
	if( pst->signFlag < data ){
		return -1;
	}
	return 0;
}
static AST ccTypeNewBasicType( AST basic, U2 typeQual ){
	if( basic == 0 ){
		return 0;
	}
	if( stTypeInfoAccess.getMax() == 0 ){
		return 0;
	}

	if( typeQual == 0 ){
		return basic;
	}
	if((typeQual & TYPEQUAL_CONST)&&( typeQual & TYPEQUAL_VOLATILE )){
		return basic + BASICTYPE_NUM*3;
	}
	if( typeQual & TYPEQUAL_VOLATILE){
		return basic+BASICTYPE_NUM*2;
	}
	return basic+BASICTYPE_NUM;
}

VOID CcTypeInitial( VOID ){
	AST i,cnt;

	gblPointerType = 0;
	gblBitfieldType = 0;
	stTypeInfoAccess.alloc(BASICTYPE_NUM*4);
	for( i = MIN_ARRAY; i <= BASICTYPE_NUM; i++ ){
		cnt = i;
		stTypeInfoAccess.typeKind.set( cnt, TYPEKIND_BASIC );
//		stTypeInfoAccess.typeQual.set( cnt, 0 );
		switch( i ){
		case xBASE_VOID :
			break;
		case xBASE_CHAR :
			stTypeInfoAccess.size.set( cnt, 1 );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			if (stCoreEnvInfo.ucCharSign == OPT_CHAR_SIGNED ){
				stTypeInfoAccess.signFlag.set( cnt, SIGN_SIGNED );
			}else{
				stTypeInfoAccess.signFlag.set( cnt, SIGN_UNSIGNED );
			}
			break;
		case xBASE_SCHAR :
			stTypeInfoAccess.size.set( cnt, 1 );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_SIGNED );
			break;
		case xBASE_UCHAR :
			stTypeInfoAccess.size.set( cnt, 1 );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_UNSIGNED );
			break;
		case xBASE_INT :
			stTypeInfoAccess.size.set( cnt, INTSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SIGNED );
//			stTypeInfoAccess.longShortFlg.set( cnt, 0 );
			break;
		case xBASE_SINT :
			stTypeInfoAccess.size.set( cnt, INTSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_SIGNED );
			break;
		case xBASE_UINT :
			stTypeInfoAccess.size.set( cnt, INTSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_UNSIGNED );
			break;
		case xBASE_SHORT :
			stTypeInfoAccess.size.set( cnt, SHORTSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_SHORT );
			break;
		case xBASE_SSHORT :
			stTypeInfoAccess.size.set( cnt, SHORTSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_SIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_SHORT );
			break;
		case xBASE_USHORT :
			stTypeInfoAccess.size.set( cnt, SHORTSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_UNSIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_SHORT );
			break;
		case xBASE_LONG  :
			stTypeInfoAccess.size.set( cnt, LONGSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_LONG );
			break;
		case xBASE_SLONG :
			stTypeInfoAccess.size.set( cnt, LONGSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_SIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_LONG );
			break;
		case xBASE_ULONG :
			stTypeInfoAccess.size.set( cnt, LONGSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_UNSIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_LONG );
			break;
		case xBASE_LLONG   :
			stTypeInfoAccess.size.set( cnt, LONGLONGSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_LONGLONG );
			break;
		case xBASE_SLLONG  :
			stTypeInfoAccess.size.set( cnt, LONGLONGSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_SIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_LONGLONG );
			break;
		case xBASE_ULLONG  :
			stTypeInfoAccess.size.set( cnt, LONGLONGSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_INT );
			stTypeInfoAccess.signFlag.set( cnt, SIGN_SPECIFY_UNSIGNED );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_LONGLONG );
			break;
		case xBASE_FLOAT   :
			stTypeInfoAccess.size.set( cnt, FLOATSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_FLOAT );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_SHORT );
			break;
		case xBASE_DOUBLE  :
			stTypeInfoAccess.size.set( cnt, DOUBLESIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_FLOAT );
			break;
		case xBASE_LDOUBLE :
			stTypeInfoAccess.size.set( cnt, FLOATSIZE );
			stTypeInfoAccess.intFloat.set( cnt, FLOATING_FLOAT );
			stTypeInfoAccess.longShortFlg.set( cnt, LENGTH_LONG );
			break;
		}

	}
	for( i = MIN_ARRAY; i <= BASICTYPE_NUM; i++ ){
		cnt = i + BASICTYPE_NUM;
		stTypeInfoAccess.copy( i, cnt, 1 );
		stTypeInfoAccess.next.set( cnt, 0  );
		stTypeInfoAccess.typeQual.set( cnt, TYPEQUAL_CONST );
		stTypeInfoAccess.noQualType.set( cnt, i );
		stTypeInfoAccess.next.set( i, cnt );
	}
	for( i = MIN_ARRAY; i <= BASICTYPE_NUM; i++ ){
		cnt = i + BASICTYPE_NUM * 2;
		stTypeInfoAccess.copy( i, cnt, 1 );
		stTypeInfoAccess.next.set( cnt, 0  );
		stTypeInfoAccess.typeQual.set( cnt, TYPEQUAL_VOLATILE );
		stTypeInfoAccess.noQualType.set( cnt, i );
		stTypeInfoAccess.next.set( i + BASICTYPE_NUM, cnt );
	}
	for( i = MIN_ARRAY; i <= BASICTYPE_NUM; i++ ){
		cnt = i + BASICTYPE_NUM * 3;
		stTypeInfoAccess.copy( i, cnt, 1 );
		stTypeInfoAccess.next.set( cnt, 0  );
		stTypeInfoAccess.typeQual.set( cnt, TYPEQUAL_CONVOL );
		stTypeInfoAccess.noQualType.set( cnt, i );
		stTypeInfoAccess.next.set( i + BASICTYPE_NUM*2, cnt );
	}
}
AST CcTypeIntegerPromotion( AST type ){
	U2  typeKind =  stTypeInfoAccess.typeKind.get( type );
	U4  typeSize;
	U2  signFlag;
	U2  precFlag;
	if( typeKind == TYPEKIND_BITFIELD ){
		type = stTypeInfoAccess.elementType.get( type );
		if( type == 0 ){
			type = xBASE_INT;
		}
		typeKind = stTypeInfoAccess.typeKind.get( type );
	}
	if( ( typeKind != TYPEKIND_BASIC && typeKind != TYPEKIND_ENUM )
		|| stTypeInfoAccess.intFloat.get( type ) != FLOATING_INT ){
		return type;
	}
	typeSize = stTypeInfoAccess.size.get(type);
	signFlag = stTypeInfoAccess.signFlag.get(type);
	precFlag = stTypeInfoAccess.longShortFlg.get(type);
	switch( precFlag ){
	case LENGTH_LONG:
		if( signFlag & SIGN_UNSIGNED ){
			type = xBASE_ULONG;
		}else{
			type = xBASE_LONG;
		}
		break;
	case LENGTH_LONGLONG:
		if( signFlag & SIGN_UNSIGNED ){
			type = xBASE_ULLONG;
		}else{
			type = xBASE_LLONG;
		}
		break;
	default:
		if( typeSize < INTSIZE ){
			type = xBASE_INT;
		}else if( typeSize == INTSIZE ){
			if( signFlag & SIGN_UNSIGNED ){
				type = xBASE_UINT;
			}else{
				type = xBASE_INT;
			}
		}else if( typeSize == LONGSIZE ){
			if( signFlag & SIGN_UNSIGNED ){
				type = xBASE_ULONG;
			}else{
				type = xBASE_LONG;
			}
		}else{
			if( signFlag & SIGN_UNSIGNED ){
				type = xBASE_ULLONG;
			}else{
				type = xBASE_LLONG;
			}
		}
		break;
	}
	return type;
}
AST CcTypeArgumentPromotion( AST type ){
	AST astNoQualType;

	type = CcTypeIntegerPromotion( type );
	astNoQualType = CcTypeGetNoQualType( type );
	if( astNoQualType == TYPE_FLOAT ){
		type = TYPE_DOUBLE;
	}
	return type;
}
AST CcTypeGetArithConversion( AST type1, AST type2 ){
	U2 typeKind;
	U4  typeSize1, typeSize2;
	U2  signFlag1, signFlag2;
	type1 = CcTypeIntegerPromotion( type1 );
	type2 = CcTypeIntegerPromotion( type2 );
	typeKind = stTypeInfoAccess.typeKind.get( type1 );
	if( typeKind != TYPEKIND_BASIC ){
		return type1;
	}
	typeKind = stTypeInfoAccess.typeKind.get( type2 );
	if( typeKind != TYPEKIND_BASIC ){
		return type2;
	}
	type1 = CcTypeGetNoQualType( type1 );
	type2 = CcTypeGetNoQualType( type2 );
	if( type1 == type2 ){
		return type1;
	}
	if( type1 == xBASE_LDOUBLE || type2 == xBASE_LDOUBLE ){
		return xBASE_LDOUBLE;
	}
	if( type1 == xBASE_DOUBLE || type2 == xBASE_DOUBLE ){
		return xBASE_DOUBLE;
	}
	if( type1 == xBASE_FLOAT || type2 == xBASE_FLOAT ){
		return xBASE_FLOAT;
	}
	if( type1 == xBASE_ULLONG || type2 == xBASE_ULLONG ){
		return xBASE_ULLONG;
	}
	if( type1 == xBASE_LLONG || type2 == xBASE_LLONG ){
		typeSize1 = stTypeInfoAccess.size.get( type1 );
		signFlag1 = stTypeInfoAccess.signFlag.get( type1 );
		typeSize2 = stTypeInfoAccess.size.get( type2 );
		signFlag2 = stTypeInfoAccess.signFlag.get( type2 );
		if( typeSize1 < typeSize2 ){
			typeSize1 = typeSize2;
			signFlag1 = signFlag2;
		}else if( typeSize1 == typeSize2 ){
			signFlag1 |= signFlag2;
		}
		if( (typeSize1 == LONGLONGSIZE) && ( signFlag1 & SIGN_UNSIGNED ) ){
			return xBASE_ULLONG;
		}
		return xBASE_LLONG;
	}
	if( type1 == xBASE_ULONG || type2 == xBASE_ULONG ){
		return xBASE_ULONG;
	}
	if( type1 == xBASE_LONG || type2 == xBASE_LONG ){
		typeSize1 = stTypeInfoAccess.size.get( type1 );
		signFlag1 = stTypeInfoAccess.signFlag.get( type1 );
		typeSize2 = stTypeInfoAccess.size.get( type2 );
		signFlag2 = stTypeInfoAccess.signFlag.get( type2 );
		if( typeSize1 < typeSize2 ){
			typeSize1 = typeSize2;
			signFlag1 = signFlag2;
		}else if( typeSize1 == typeSize2 ){
			signFlag1 |= signFlag2;
		}
		if( (typeSize1 == LONGLONGSIZE) && ( signFlag1 & SIGN_UNSIGNED ) ){
			return xBASE_ULONG;
		}
		return xBASE_LONG;
	}
	if( type1 == xBASE_UINT || type2 == xBASE_UINT ){
		return xBASE_UINT;
	}
	return xBASE_INT;

}
AST CcTypeGetNoQualType( AST astType ){
	AST astOrign;
	astOrign = stTypeInfoAccess.noQualType.get( astType );
	while( astOrign ){
		astType = astOrign;
		astOrign = stTypeInfoAccess.noQualType.get( astType );
	}
	return astType;
}
/*  type create functions */
AST CcTypeGetBasicType( PSZ str, U2 typeQual  ){
	AST basic=0;
	const BASICTYPEINFO * ptr = NULL;
	if( str == NULL ){
		return basic;
	}
	switch( *str ){
	case	'v' 	:
		ptr = stBasicType_v;
		break;
	case	'c' 	:
		ptr = stBasicType_c;
		break;
	case	's' 	:
		ptr = stBasicType_s;
		break;
	case	'u'	:
		ptr = stBasicType_u;
		break;
	case	'l'	:
		ptr = stBasicType_l;
		break;
	case	'f'	:
		ptr = stBasicType_f;
		break;
	case	'd'	:
		ptr = stBasicType_d;
		break;
	case	'i' 	:
		ptr = stBasicType_i;
		break;
	default:
		return basic;
	}
	while( ptr->name != NULL ){
		if( 0 == strcmp( ptr->name, str ) ){
			basic = ptr->type;
			break;
		}
		ptr++;
	}
	return ccTypeNewBasicType( basic, typeQual );
}


AST   CcTypeAddPointer( AST astBasic, U4 size, U2 qual ){
	AST  astNew, astOrign;
	AST  astPre, astCurr;
	TYPEINFO_COMPPOINTER_FORTREE ptr;

	if( astBasic == 0 ){
		return 0;
	}
	if( size == 0 ){
		size = CcTypeGetDefaultPointerSize();
	}
	ptr.astBasic = astBasic;
	ptr.tagInfo = 0;
	ptr.size = size;
	astOrign = stTypeInfoAccess.addType( gblPointerType,  &gblPointerType, &ptr, ccTypeCompPointer_forTree );
	stTypeInfoAccess.typeKind.set( astOrign, TYPEKIND_POINTER );
	stTypeInfoAccess.elementType.set( astOrign, astBasic );
	stTypeInfoAccess.size.set( astOrign, size );
	stTypeInfoAccess.tagInfo.set( astOrign, 0 );
	if( qual == 0 ){
		return astOrign;
	}
	astPre = astOrign;
	astCurr = stTypeInfoAccess.next.get( astOrign );
	while( astCurr ){
		if( qual == stTypeInfoAccess.typeQual.get( astCurr ) ){
			return astCurr;
		}
		astPre = astCurr;
		astCurr = stTypeInfoAccess.next.get( astCurr );
	}
	stTypeInfoAccess.alloc(1);
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.copy( astOrign, astNew, 1 );
	stTypeInfoAccess.next.set(  astNew,0 );
	stTypeInfoAccess.typeQual.set( astNew, qual );
	stTypeInfoAccess.noQualType.set( astNew, astOrign) ;
	stTypeInfoAccess.next.set( astPre, astNew) ;
	return astNew;
}
AST   CcTypeAddArray( AST astBasic, U4 size ){
	AST  astNew;
	BOOL bret;

	if( astBasic == 0 ){
		return 0;
	}
	bret = stTypeInfoAccess.alloc(1);
	if( bret != TRUE ){
		return 0;
	}
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.typeKind.set( astNew, TYPEKIND_ARRAY );
	stTypeInfoAccess.size.set( astNew, size );
	stTypeInfoAccess.tagInfo.set( astNew, 0 );
	stTypeInfoAccess.elementType.set( astNew, astBasic );
	return astNew;
}
AST   CcTypeResetArraySize( AST astArray, U4 newsize ){
	if( astArray == 0 ){
		return 0;
	}
	stTypeInfoAccess.size.set( astArray, newsize );
	return astArray;
}
AST  CcTypeAddDefaultEnum( AST tagInfo ){
	BOOL bret;
	AST  astNew;

	bret = stTypeInfoAccess.alloc(1);
	if( bret != TRUE ){
		return 0;
	}
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.copy( stCoreEnvInfo.astEnumType, astNew, 1 );

	stTypeInfoAccess.next.set( astNew, 0 );
	stTypeInfoAccess.memChain.set( astNew, 0 );
	stTypeInfoAccess.typeKind.set( astNew, TYPEKIND_ENUM );
	stTypeInfoAccess.tagInfo.set( astNew, tagInfo );

	return astNew;
}
AST  CcTypeAddEnum( AST tagInfo, AST astBasicType, AST memChain ){
	BOOL bret;
	AST  astNew;

	bret = stTypeInfoAccess.alloc(1);
	if( bret != TRUE ){
		return 0;
	}
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.copy( astBasicType, astNew, 1 );
	stTypeInfoAccess.memChain.set( astNew, memChain );
	stTypeInfoAccess.typeKind.set( astNew, TYPEKIND_ENUM );
	stTypeInfoAccess.tagInfo.set( astNew, tagInfo );

	return astNew;
}
AST  CcTypeAddQualifiedType( AST astBasicType, U2 qual ){
	AST  astNew;
	AST  astCurr;
	AST  astPre;
	if( qual == 0 || astBasicType == 0 ){
		return astBasicType;
	}
	if( 0 != stTypeInfoAccess.noQualType.get( astBasicType ) ){
		astBasicType = stTypeInfoAccess.noQualType.get( astBasicType );
	}
	astPre = astBasicType;
	astCurr = stTypeInfoAccess.next.get( astPre );
	while( astCurr ){
		if( qual == stTypeInfoAccess.typeQual.get( astCurr )){
			return astCurr;
		}
		astPre = astCurr;
		astCurr = stTypeInfoAccess.next.get( astPre );
	}
	stTypeInfoAccess.alloc(1);
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.copy( astBasicType, astNew, 1 );
	stTypeInfoAccess.next.set( astNew, 0 );
	stTypeInfoAccess.typeQual.set( astNew, qual );
	stTypeInfoAccess.noQualType.set( astNew, astBasicType ) ;
	stTypeInfoAccess.next.set( astPre, astNew) ;
	return astNew;
}
AST  CcTypeAddStruct( AST tagInfo, AST memChain, U4 size ){
	BOOL bret;
	AST  astNew;

	bret = stTypeInfoAccess.alloc(1);
	if( bret != TRUE ){
		return 0;
	}
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.typeKind.set( astNew, TYPEKIND_STRUCT );
	stTypeInfoAccess.memChain.set( astNew, memChain );
	stTypeInfoAccess.size.set( astNew, size );
	stTypeInfoAccess.tagInfo.set( astNew, tagInfo );
	return astNew;
}
AST  CcTypeAddUnion( AST tagInfo, AST memChain, U4 size){
	BOOL bret;
	AST  astNew;

	bret = stTypeInfoAccess.alloc(1);
	if( bret != TRUE ){
		return 0;
	}
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.typeKind.set( astNew, TYPEKIND_UNION );
	stTypeInfoAccess.memChain.set( astNew, memChain );
	stTypeInfoAccess.size.set( astNew, size );
	stTypeInfoAccess.tagInfo.set( astNew, tagInfo );
	return astNew;
}
AST  CcTypeAddFunction( AST returnType, AST memChain){
	BOOL bret;
	AST  astNew;
	bret = stTypeInfoAccess.alloc(1);
	if( bret != TRUE ){
		return 0;
	}
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.typeKind.set( astNew, TYPEKIND_FUNCTION );
	stTypeInfoAccess.elementType.set( astNew, returnType );
	stTypeInfoAccess.memChain.set( astNew, memChain );
	return astNew;
}
AST  CcTypeAddBitfield( AST intType, U4 size, U2 signFlag, U2 qual ){
	AST  astOrign, astNew;
	AST  astPre, astCurr;
	TYPEINFO_COMPBITFIELD_FORTREE ptr;

	if( intType == 0 ){
		return 0;
	}
	ptr.intType = intType;
	ptr.signFlag = signFlag;
	ptr.size = size;
	astOrign = stTypeInfoAccess.addType( gblBitfieldType, &gblBitfieldType, &ptr, ccTypeCompBitfield_forTree );
	stTypeInfoAccess.typeKind.set( astOrign, TYPEKIND_BITFIELD );
	stTypeInfoAccess.elementType.set( astOrign, intType );
	stTypeInfoAccess.size.set( astOrign, size );
	stTypeInfoAccess.signFlag.set( astOrign, signFlag );
	if( qual == 0 ){
		return astOrign;
	}
	astPre = astOrign;
	astCurr = stTypeInfoAccess.next.get( astOrign );
	while( astCurr ){
		if( qual == stTypeInfoAccess.typeQual.get( astCurr ) ){
			return astCurr;
		}
		astPre = astCurr;
		astCurr = stTypeInfoAccess.next.get( astCurr );
	}
	stTypeInfoAccess.alloc(1);
	astNew = stTypeInfoAccess.getMax();
	stTypeInfoAccess.copy( astOrign, astNew, 1 );
	stTypeInfoAccess.next.set( astNew, 0 );
	stTypeInfoAccess.typeQual.set( astNew, qual );
	stTypeInfoAccess.noQualType.set( astNew, astOrign) ;
	stTypeInfoAccess.next.set( astPre, astNew) ;
	return astNew;
}
AST  CcTypeGetWCharType( VOID ){
	return xBASE_CHAR;
//	if( WCHARSIZE == CHARSIZE ){
//		return xBASE_CHAR;
//	}
//	if( WCHARSIZE == SHORTSIZE ){
//		if( stCoreEnvInfo.ucCharSign == OPT_CHAR_SIGNED ){
//			return xBASE_SHORT;
//		}else{
//			return xBASE_USHORT;
//		}
//	}
//	if( WCHARSIZE == INTSIZE ){
//		if( stCoreEnvInfo.ucCharSign == OPT_CHAR_SIGNED ){
//			return xBASE_INT;
//		}else{
//			return xBASE_UINT;
//		}
//	}
//	if( stCoreEnvInfo.ucCharSign == OPT_CHAR_SIGNED ){
//		return xBASE_LONG;
//	}
//
//	return xBASE_ULONG;
}

BOOL  CcTypeIsInt( AST type ){
	if( stTypeInfoAccess.noQualType.get( type ) ){
		type = stTypeInfoAccess.noQualType.get( type );
	}
	if( type != xBASE_INT && type != xBASE_SINT && type != xBASE_UINT ){
		return FALSE;
	}
	return TRUE;
}
U2    CcTypeCreateQualifier( S2 constNum, S2 volatileNum, S2 restrictNum ){
	U2 qualifier = 0;
	if( constNum > 0 ){
		qualifier |= TYPEQUAL_CONST;
	}
	if( volatileNum > 0 ){
		qualifier |= TYPEQUAL_VOLATILE;
	}
	if( restrictNum > 0 ){
		qualifier |= TYPEQUAL_RESTRICT;
	}
	return qualifier;
}

VOID  CcTypeSetUnionStructInfo(AST astTypeInfo, AST astParamChain, U4 ulSize ){
	astTypeInfo = CcTypeGetNoQualType(astTypeInfo);
	while(astTypeInfo){
		stTypeInfoAccess.memChain.set( astTypeInfo, astParamChain );
		stTypeInfoAccess.size.set( astTypeInfo, ulSize );
		astTypeInfo = stTypeInfoAccess.next.get( astTypeInfo );
	}
}
U4   CcTypeGetDefaultPointerSize( VOID ){
	if( stCoreEnvInfo.ucNearFar ){
		return NEARPOINTERSIZE;
	}
	return POINTERSIZE;
}

BOOL CcTypeIsModifiableObj( AST astType ){
	AST astMemChain;
	AST astSym;
	AST astMemType;
	if( CcTypeIsConst( astType ) || CcTypeIsFunction( astType )){
		return FALSE;
	}
	if( CcTypeIsArray( astType ) ){
		return CcTypeIsModifiableObj( stTypeInfoAccess.elementType.get( astType ));
	}
	if( CcTypeIsStruct( astType ) || CcTypeIsUnion( astType ) ){
		astMemChain = stTypeInfoAccess.memChain.get( astType );
		while( astMemChain ){
			astSym = stUniteChainAccess.parameter_sym.get( astMemChain );
			astMemType = stSymbolInfoAccess.type.get( astSym );
			while( CcTypeIsArray( astMemType ) ){
				astMemType = stTypeInfoAccess.elementType.get( astMemType );
			}
			if( CcTypeIsModifiableObj( astMemType ) == FALSE ){
				return FALSE;
			}
			astMemChain = stUniteChainAccess.next.get( astMemChain );
		}
	}
	return TRUE;
}
BOOL CcTypeIsAssignable( AST astOrg, AST astDst ){
	BOOL bResult = TRUE;
	U2  usLQual = 0;
	U2  usRQual = 0;

	flgType &= ~ASSIGN_FLAG_BITS;
	if( astOrg == astDst ){
		return TRUE;
	}
	if( astOrg == 0 || astDst == 0 ){
		flgType = COMP_ASSIGN_ILLEGAL;
		return FALSE;
	}
	astOrg = CcTypeIntegerPromotion( astOrg );
	astDst = CcTypeIntegerPromotion( astDst );
	if( CcTypeIsArith( astOrg ) && CcTypeIsArith( astDst ) ){
		return TRUE;
	}
	/*debug,13/2/7,S*/
	else if(CcTypeIsPointer(astDst) && CcTypeIsInteger(astOrg)){
		return TRUE;
	}
	/*debug,13/2/7,E*/
	else if( CcTypeIsPointer( astDst ) && CcTypeIsPointer( astOrg ) ){
		astDst = stTypeInfoAccess.elementType.get( astDst );
		astOrg = stTypeInfoAccess.elementType.get( astOrg );
		usLQual = stTypeInfoAccess.typeQual.get( astDst );
		usRQual = stTypeInfoAccess.typeQual.get( astOrg );
		astDst = CcTypeGetNoQualType( astDst );
		astOrg = CcTypeGetNoQualType( astOrg );
		/*debug,13/2/7,S*/
		if( astDst == TYPE_VOID /*&& (stTypeInfoAccess.typeKind.get(astOrg)!=TYPEKIND_FUNCTION)*/){
			bResult = TRUE;
		}else if( astOrg == TYPE_VOID /*&& (stTypeInfoAccess.typeKind.get(astDst)!=TYPEKIND_FUNCTION)*/){
			bResult = TRUE;
		}else{
			bResult = CcTypeIsCompatible(astDst,astOrg);
		}
		/*debug,13/2/7,E*/
		if( bResult == TRUE ){
			if( ( usLQual & usRQual & TYPEQUAL_CONVOL ) == ( usRQual & TYPEQUAL_CONVOL )){
				bResult = TRUE;
			}else{
				bResult = FALSE;
				flgType |= COMP_ASSIGN_DIFFQUALIFY_POINTER;
			}
		}else{
			flgType |= COMP_ASSIGN_UNCOMPATIBLE_POINTER;
		}
	}else{
		usLQual = stTypeInfoAccess.typeQual.get( astDst );
		usRQual = stTypeInfoAccess.typeQual.get( astOrg );
		astDst = CcTypeGetNoQualType( astDst );
		astOrg = CcTypeGetNoQualType( astOrg );
		bResult = CcTypeIsCompatible(astDst,astOrg);
		if( bResult == FALSE ){
			flgType |= COMP_ASSIGN_UNCOMPATIBLE;
		}
	}
	return bResult;
}
static BOOL ccTypeSaveStUn( AST astType1st, AST astType2nd ){
	AST astCnt, astMax;
	astMax = stTypeCmpStkAccess.getMax();
	for( astCnt = MIN_ARRAY; astCnt <= astMax; astCnt ++ ){
		if( stTypeCmpStkAccess.type1st.get( astCnt ) == astType1st
			&& stTypeCmpStkAccess.type2nd.get( astCnt ) == astType2nd ){
			return TRUE;
		}
	}
	stTypeCmpStkAccess.alloc(1);
	astMax = stTypeCmpStkAccess.getMax();
	stTypeCmpStkAccess.type1st.set( astMax, astType1st );
	stTypeCmpStkAccess.type2nd.set( astMax, astType2nd );
	return FALSE;
}
static BOOL ccTypeIsCompatible( AST astType1st, AST astType2nd ){
	U2 usQual1st, usQual2nd;
	BOOL bResult = TRUE;
	AST astSymChain1, astSymChain2;
	AST astSymInfo1,astSymInfo2;
	PSZ pszSymbolName1,pszSymbolName2;
	S4  num1, num2;

	if( astType1st == astType2nd ){
		return TRUE;
	}
	while( astType1st != 0 ){
		if( astType2nd == 0 ){
			return FALSE;
		}
		if( astType1st == astType2nd ){
			return TRUE;
		}
		if( stTypeInfoAccess.typeKind.get( astType1st )
			!= stTypeInfoAccess.typeKind.get( astType2nd ) ){
			return FALSE;
		}
		switch(stTypeInfoAccess.typeKind.get( astType1st )){
			case TYPEKIND_BASIC:{
				usQual1st = stTypeInfoAccess.typeQual.get( astType1st );
				usQual2nd = stTypeInfoAccess.typeQual.get( astType2nd );
				/*debug,13/2/7,S*/
//				astType1st = CcTypeGetNoQualType( astType1st );
//				astType2nd = CcTypeGetNoQualType( astType2nd );
//				if( astType1st != astType2nd ){
//					bResult = FALSE;
//					if(astType1st == TYPE_INT || astType1st==TYPE_SIGNED_INT ){
//						if(astType2nd == TYPE_INT || astType2nd==TYPE_SIGNED_INT ){
//							bResult = TRUE;
//						}
//					}
//					if(astType1st == TYPE_SHORT || astType1st==TYPE_SIGNED_SHORT ){
//						if(astType2nd == TYPE_SHORT || astType2nd==TYPE_SIGNED_SHORT ){
//							bResult = TRUE;
//						}
//					}
//					if(astType1st == TYPE_LONG || astType1st==TYPE_SIGNED_LONG ){
//						if(astType2nd == TYPE_LONG || astType2nd==TYPE_SIGNED_LONG ){
//							bResult = TRUE;
//						}
//					}
//					if(astType1st == TYPE_LONG_LONG || astType1st==TYPE_SIGNED_LONG_LONG){
//						if(astType2nd == TYPE_LONG_LONG || astType2nd==TYPE_SIGNED_LONG_LONG ){
//							bResult = TRUE;
//						}
//					}
//					if( bResult == FALSE ){
//						return FALSE;
//					}
//				}
				/*debug,13/2/7,E*/
				if( usQual1st != usQual2nd ){
					return FALSE;
				}
				return TRUE;
			}
			case TYPEKIND_ARRAY:{
				U4 size1st = stTypeInfoAccess.size.get( astType1st );
				U4 size2nd = stTypeInfoAccess.size.get( astType2nd );
				usQual1st = stTypeInfoAccess.typeQual.get( astType1st );
				usQual2nd = stTypeInfoAccess.typeQual.get( astType2nd );
				if ( usQual1st != usQual2nd ){
					return FALSE;
				}
				if( size1st != 0 && size2nd != 0 && size1st != size2nd ){
					return FALSE;
				}
				astType1st = stTypeInfoAccess.elementType.get(astType1st);
				astType2nd = stTypeInfoAccess.elementType.get(astType2nd);
				continue ;
			}
			case  TYPEKIND_POINTER :{
				usQual1st = stTypeInfoAccess.typeQual.get( astType1st );
				usQual2nd = stTypeInfoAccess.typeQual.get( astType2nd );
				if ( usQual1st != usQual2nd ){
					return FALSE;
				}
				astType1st = stTypeInfoAccess.elementType.get(astType1st);
				astType2nd = stTypeInfoAccess.elementType.get(astType2nd);
				continue ;
			}
			case TYPEKIND_BITFIELD :{
				U4 size1st = stTypeInfoAccess.size.get( astType1st );
				U4 size2nd = stTypeInfoAccess.size.get( astType2nd );
				usQual1st = stTypeInfoAccess.typeQual.get( astType1st );
				usQual2nd = stTypeInfoAccess.typeQual.get( astType2nd );
				if ( usQual1st != usQual2nd ){
					return FALSE;
				}
				if( size1st != size2nd ){
					return FALSE;
				}
				astType1st = stTypeInfoAccess.elementType.get(astType1st);
				astType2nd = stTypeInfoAccess.elementType.get(astType2nd);
				continue ;
			}
			case TYPEKIND_STRUCT :{

				usQual1st = stTypeInfoAccess.typeQual.get( astType1st );
				usQual2nd = stTypeInfoAccess.typeQual.get( astType2nd );
				if ( usQual1st != usQual2nd ){
					return FALSE;
				}
				astType1st = CcTypeGetNoQualType( astType1st );
				astType2nd = CcTypeGetNoQualType( astType2nd );
				if( astType1st == astType2nd ){
					return TRUE;
				}
				astSymInfo1 = stTypeInfoAccess.tagInfo.get(  astType1st  ) ;
				astSymInfo2 = stTypeInfoAccess.tagInfo.get( astType2nd ) ;
				if( astSymInfo1 != astSymInfo2 ){
					pszSymbolName1 = stSymbolInfoAccess.name.get( astSymInfo1 );
					pszSymbolName2 = stSymbolInfoAccess.name.get( astSymInfo2 );
					if( pszSymbolName1 != NULL
						&& pszSymbolName2 != NULL
						&& strcmp(pszSymbolName1, pszSymbolName2) != 0 ){
						return FALSE;
					}
				}
				bResult = ccTypeSaveStUn( astType1st, astType2nd );
				if( bResult == TRUE ){
					return TRUE;
				}
				if( stTypeInfoAccess.size.get( astType1st )
					!= stTypeInfoAccess.size.get( astType2nd )){
					return FALSE;
				}
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
				while( astSymChain1 != 0 ){
					if( astSymChain2 == 0 ){
						return FALSE;
					}
					astSymInfo1 = stUniteChainAccess.parameter_sym.get( astSymChain1 ) ;
					astSymInfo2 = stUniteChainAccess.parameter_sym.get( astSymChain2 ) ;
					if( astSymInfo1 != astSymInfo2 ){
						pszSymbolName1 = stSymbolInfoAccess.name.get( astSymInfo1 );
						pszSymbolName2 = stSymbolInfoAccess.name.get( astSymInfo2 );
						if( pszSymbolName1 != NULL
							&& pszSymbolName2 != NULL
							&& strcmp(pszSymbolName1, pszSymbolName2) != 0 ){
							return FALSE;
						}
						astType1st = stSymbolInfoAccess.type.get( astSymInfo1 );
						astType2nd = stSymbolInfoAccess.type.get( astSymInfo2 );
						bResult = ccTypeIsCompatible( astType1st, astType2nd );
						if( bResult == FALSE ){
							return FALSE;
						}
					}
					astSymChain1 = stUniteChainAccess.next.get( astSymChain1 ) ;
					astSymChain2 = stUniteChainAccess.next.get( astSymChain2 ) ;
				}
				if( astSymChain2 != 0 )	{
					return FALSE;
				}

				return TRUE;
			}
			case TYPEKIND_UNION :{
				usQual1st = stTypeInfoAccess.typeQual.get( astType1st );
				usQual2nd = stTypeInfoAccess.typeQual.get( astType2nd );
				if ( usQual1st != usQual2nd ){
					return FALSE;
				}
				astType1st = CcTypeGetNoQualType( astType1st );
				astType2nd = CcTypeGetNoQualType( astType2nd );
				if( astType1st == astType2nd ){
					return TRUE;
				}
				astSymInfo1 = stTypeInfoAccess.tagInfo.get(  astType1st  ) ;
				astSymInfo2 = stTypeInfoAccess.tagInfo.get( astType2nd ) ;
				if( astSymInfo1 != astSymInfo2 ){
					pszSymbolName1 = stSymbolInfoAccess.name.get( astSymInfo1 );
					pszSymbolName2 = stSymbolInfoAccess.name.get( astSymInfo2 );
					if( pszSymbolName1 != NULL
						&& pszSymbolName2 != NULL
						&& strcmp(pszSymbolName1, pszSymbolName2) != 0 ){
						return FALSE;
					}
				}
				bResult = ccTypeSaveStUn( astType1st, astType2nd );
				if( bResult == TRUE ){
					return TRUE;
				}
				num1 = 0;
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				while( astSymChain1 ){
					num1++;
					astSymChain1 = stUniteChainAccess.next.get( astSymChain1 ) ;
				}
				num2 = 0;
				astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
				while( astSymChain2 ){
					num2++;
					astSymChain2 = stUniteChainAccess.next.get( astSymChain2 ) ;
				}
				if( num1 != num2 ){
					return FALSE;
				}
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				while( astSymChain1 != 0 ){
					astSymInfo1 = stUniteChainAccess.parameter_sym.get( astSymChain1 ) ;
					astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
					while( astSymChain2 != 0 ){
						astSymInfo2 = stUniteChainAccess.parameter_sym.get( astSymChain2 ) ;
						if( astSymInfo1 != astSymInfo2 ){
							pszSymbolName1 = stSymbolInfoAccess.name.get( astSymInfo1 );
							pszSymbolName2 = stSymbolInfoAccess.name.get( astSymInfo2 );
							if( strcmp(pszSymbolName1, pszSymbolName2) == 0 ){
								astType1st = stSymbolInfoAccess.type.get( astSymInfo1 );
								astType2nd = stSymbolInfoAccess.type.get( astSymInfo2 );
								bResult = ccTypeIsCompatible( astType1st, astType2nd );
								if( bResult == TRUE ){
									break;
								}
							}
						}
						astSymChain2 = stUniteChainAccess.next.get( astSymChain2 ) ;
					}
					if( astSymChain2 == 0 ){
						return FALSE;
					}
					astSymChain1 = stUniteChainAccess.next.get( astSymChain1 ) ;
				}

				return TRUE;
			}
			case  TYPEKIND_ENUM :{
				usQual1st = stTypeInfoAccess.typeQual.get( astType1st );
				usQual2nd = stTypeInfoAccess.typeQual.get( astType2nd );
				if ( usQual1st != usQual2nd ){
					return FALSE;
				}
				astType1st = CcTypeGetNoQualType( astType1st );
				astType2nd = CcTypeGetNoQualType( astType2nd );
				if( astType1st == astType2nd ){
					return TRUE;
				}
				astSymInfo1 = stTypeInfoAccess.tagInfo.get(  astType1st  ) ;
				astSymInfo2 = stTypeInfoAccess.tagInfo.get( astType2nd ) ;
				if( astSymInfo1 != astSymInfo2 ){
					pszSymbolName1 = stSymbolInfoAccess.name.get( astSymInfo1 );
					pszSymbolName2 = stSymbolInfoAccess.name.get( astSymInfo2 );
					if( pszSymbolName1 != NULL
						&& pszSymbolName2 != NULL
						&& strcmp(pszSymbolName1, pszSymbolName2) != 0 ){
						return FALSE;
					}
				}
				bResult = ccTypeSaveStUn( astType1st, astType2nd );
				if( bResult == TRUE ){
					return TRUE;
				}
				num1 = 0;
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				while( astSymChain1 ){
					num1++;
					astSymChain1 = stUniteChainAccess.next.get( astSymChain1 ) ;
				}
				num2 = 0;
				astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
				while( astSymChain2 ){
					num2++;
					astSymChain2 = stUniteChainAccess.next.get( astSymChain2 ) ;
				}
				if( num1 != num2 ){
					return FALSE;
				}
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				while( astSymChain1 != 0 ){
					astSymInfo1 = stUniteChainAccess.parameter_sym.get( astSymChain1 ) ;
					astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
					while( astSymChain2 != 0 ){
						astSymInfo2 = stUniteChainAccess.parameter_sym.get( astSymChain2 ) ;
						if( astSymInfo1 != astSymInfo2 ){
							pszSymbolName1 = stSymbolInfoAccess.name.get( astSymInfo1 );
							pszSymbolName2 = stSymbolInfoAccess.name.get( astSymInfo2 );
							if( strcmp(pszSymbolName1, pszSymbolName2) == 0 ){
								astType1st = stSymbolInfoAccess.type.get( astSymInfo1 );
								astType2nd = stSymbolInfoAccess.type.get( astSymInfo2 );
								num1 = CcValueCompareIdx( stSymbolInfoAccess.value.get( astSymInfo1 ),
										stSymbolInfoAccess.value.get( astSymInfo2 ) );
								if( num1 == 0 ){
									break;
								}
							}
						}
						astSymChain2 = stUniteChainAccess.next.get( astSymChain2 ) ;
					}
					if( astSymChain2 == 0 ){
						return FALSE;
					}
					astSymChain1 = stUniteChainAccess.next.get( astSymChain1 ) ;
				}

				return TRUE;
			}

			case TYPEKIND_FUNCTION : {
				bResult = ccTypeSaveStUn( astType1st, astType2nd );
				if( bResult == TRUE ){
					return TRUE;
				}
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
				if( astSymChain1 != 0 && astSymChain2 != 0 ){
					while( astSymChain1 != 0 ){
						astSymInfo1 = stUniteChainAccess.parameter_sym.get( astSymChain1 ) ;
						astSymInfo2 = stUniteChainAccess.parameter_sym.get( astSymChain2 ) ;
						if( astSymInfo1 != astSymInfo2 ){
							astType1st = stSymbolInfoAccess.type.get( astSymInfo1 );
							astType2nd = stSymbolInfoAccess.type.get( astSymInfo2 );
							bResult = ccTypeIsCompatible( astType1st, astType2nd );
							if( bResult == FALSE ){
								return FALSE;
							}
						}
						astSymChain1 = stUniteChainAccess.next.get( astSymChain1 );
						astSymChain2 = stUniteChainAccess.next.get( astSymChain2 );
					}

					if( astSymChain2 != 0 ){
						return FALSE;
					}
				}

				astType1st = stTypeInfoAccess.elementType.get(astType1st);
				astType2nd = stTypeInfoAccess.elementType.get(astType2nd);
				continue ;
			}

			default :{
				return FALSE;
			}
		}
	}
	if( astType1st == astType2nd ){
		return TRUE;
	}
	return FALSE;
}
BOOL CcTypeIsCompatible( AST astType1st, AST astType2nd ){
	BOOL bResult = TRUE;
	flgType &= ~COMPATIBLE_FLAG_BITS;
	stTypeCmpStkAccess.clear();
	bResult = ccTypeIsCompatible(  astType1st,  astType2nd );
	stTypeCmpStkAccess.clear();
	return bResult;
}
AST CcTypeGetCompositeType( AST astType1st, AST astType2nd ){
	BOOL bResult = TRUE;
	AST astSymChain1, astSymChain2;
	AST astSymInfo1,astSymInfo2;
	PSZ pszSymbolName1,pszSymbolName2;

	if( astType1st == astType2nd ){
		return astType1st;
	}
	bResult = ccTypeIsCompatible(  astType1st,  astType2nd );
	if( bResult == FALSE ){
		return 0;
	}
	while( astType1st != 0 ){
		if( astType1st == astType2nd ){
			break;
		}
		switch(stTypeInfoAccess.typeKind.get( astType1st )){
			case TYPEKIND_BASIC:
				break;
			case TYPEKIND_ARRAY:{
				U4 size1st = stTypeInfoAccess.size.get( astType1st );
				U4 size2nd = stTypeInfoAccess.size.get( astType2nd );
				if( size1st == 0  ){
					stTypeInfoAccess.size.set( astType1st, size2nd );
				}
				astType1st = stTypeInfoAccess.elementType.get(astType1st);
				astType2nd = stTypeInfoAccess.elementType.get(astType2nd);
				continue ;
			}
			case  TYPEKIND_POINTER :{
				astType1st = stTypeInfoAccess.elementType.get(astType1st);
				astType2nd = stTypeInfoAccess.elementType.get(astType2nd);
				continue ;
			}
			case TYPEKIND_BITFIELD :
				break;
			case TYPEKIND_STRUCT :{
				astType1st = CcTypeGetNoQualType( astType1st );
				astType2nd = CcTypeGetNoQualType( astType2nd );
				if( astType1st == astType2nd ){
					return TRUE;
				}
				bResult = ccTypeSaveStUn( astType1st, astType2nd );
				if( bResult == TRUE ){
					return TRUE;
				}
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
				while( astSymChain1 != 0 ){
					astSymInfo1 = stUniteChainAccess.parameter_sym.get( astSymChain1 ) ;
					astSymInfo2 = stUniteChainAccess.parameter_sym.get( astSymChain2 ) ;
					if( astSymInfo1 != astSymInfo2 ){
						astType1st = stSymbolInfoAccess.type.get( astSymInfo1 );
						astType2nd = stSymbolInfoAccess.type.get( astSymInfo2 );
						astType1st = CcTypeGetCompositeType( astType1st, astType2nd );
						stSymbolInfoAccess.type.set( astSymInfo1, astType1st  );
						stSymbolInfoAccess.type.set( astSymInfo2, astType1st  );
					}
					astSymChain1 = stUniteChainAccess.next.get( astSymChain1 ) ;
					astSymChain2 = stUniteChainAccess.next.get( astSymChain2 ) ;
				}
				break;
			}
			case TYPEKIND_UNION :{
				bResult = ccTypeSaveStUn( astType1st, astType2nd );
				if( bResult == TRUE ){
					return TRUE;
				}
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				while( astSymChain1 != 0 ){
					astSymInfo1 = stUniteChainAccess.parameter_sym.get( astSymChain1 ) ;
					astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
					while( astSymChain2 != 0 ){
						astSymInfo2 = stUniteChainAccess.parameter_sym.get( astSymChain2 ) ;
						if( astSymInfo1 != astSymInfo2 ){
							pszSymbolName1 = stSymbolInfoAccess.name.get( astSymInfo1 );
							pszSymbolName2 = stSymbolInfoAccess.name.get( astSymInfo2 );
							if( strcmp(pszSymbolName1, pszSymbolName2) == 0 ){
								astType1st = stSymbolInfoAccess.type.get( astSymInfo1 );
								astType2nd = stSymbolInfoAccess.type.get( astSymInfo2 );
								astType1st = CcTypeGetCompositeType( astType1st, astType2nd );
								stSymbolInfoAccess.type.set( astSymInfo1, astType1st  );
								stSymbolInfoAccess.type.set( astSymInfo2, astType1st  );
							}
						}
						astSymChain2 = stUniteChainAccess.next.get( astSymChain2 ) ;
					}
					astSymChain1 = stUniteChainAccess.next.get( astSymChain1 ) ;
				}
				break;
			}
			case  TYPEKIND_ENUM :
				break;
			case TYPEKIND_FUNCTION : {
				bResult = ccTypeSaveStUn( astType1st, astType2nd );
				if( bResult == TRUE ){
					return TRUE;
				}
				astSymChain1 = stTypeInfoAccess.memChain.get( astType1st );
				astSymChain2 = stTypeInfoAccess.memChain.get( astType2nd );
				if( astSymChain1 == 0 ){
					stTypeInfoAccess.memChain.set( astType1st, astSymChain2  );
				}else if( astSymChain1 != 0 && astSymChain2 != 0 ){
					while( astSymChain1 != 0 ){
						astSymInfo1 = stUniteChainAccess.parameter_sym.get( astSymChain1 ) ;
						astSymInfo2 = stUniteChainAccess.parameter_sym.get( astSymChain2 ) ;
						if( astSymInfo1 != astSymInfo2 ){
							astType1st = stSymbolInfoAccess.type.get( astSymInfo1 );
							astType2nd = stSymbolInfoAccess.type.get( astSymInfo2 );
							astType1st = CcTypeGetCompositeType( astType1st, astType2nd );
							stSymbolInfoAccess.type.set( astSymInfo1, astType1st  );
							stSymbolInfoAccess.type.set( astSymInfo2, astType1st  );
						}
						astSymChain1 = stUniteChainAccess.next.get( astSymChain1 );
						astSymChain2 = stUniteChainAccess.next.get( astSymChain2 );
					}
				}
				astType1st = stTypeInfoAccess.elementType.get(astType1st);
				astType2nd = stTypeInfoAccess.elementType.get(astType2nd);
				continue ;
			}
			default :
				break;
		}
		break;
	}
	return astType1st;
}
U2   CcTypeCatchAssignableFlg( VOID ){
	return flgType & ASSIGN_FLAG_BITS;
}
U2   CcTypeCatchCompatibleFlg( VOID ){
	return flgType & COMPATIBLE_FLAG_BITS;
}
static AST ccTypeGetObjMapSingle( AST astType ){
	AST astObjMap;
	stObjectMapOfTypeAccess.alloc(1);
	astObjMap = stObjectMapOfTypeAccess.getMax();
	stObjectMapOfTypeAccess.type.set( astObjMap, astType );
	return astObjMap;
}
static AST ccTypeGetObjMapStruct( AST astType ){
	AST astObjMap;
	AST astMemChain;
	AST astSym;
	PSZ pszName;
	AST astMemType;
	AST astMemObj;
	AST astPreMem;

	stObjectMapOfTypeAccess.alloc(1);
	astObjMap = stObjectMapOfTypeAccess.getMax();
	stObjectMapOfTypeAccess.type.set( astObjMap, astType );

	astMemChain = stTypeInfoAccess.memChain.get( astType );
	astPreMem = 0;
	while( astMemChain > 0  ){
		astSym = stUniteChainAccess.parameter_sym.get( astMemChain );
		pszName = stSymbolInfoAccess.name.get( astSym );
		if( str_length( pszName ) == 0 ){
			astMemChain = stUniteChainAccess.next.get( astMemChain );
			continue;
		}
		astMemType = stSymbolInfoAccess.type.get( astSym );
		astMemObj = CcTypeGetObjMap(astMemType);
		stObjectMapOfTypeAccess.sym.set( astMemObj, astSym );
		if( astPreMem == 0 ){
			stObjectMapOfTypeAccess.child.set( astObjMap, astMemObj );
		}else{
			stObjectMapOfTypeAccess.NextObj.set( astPreMem, astMemObj );
		}
		stObjectMapOfTypeAccess.parent.set( astMemObj, astObjMap );
		astPreMem = astMemObj;
		astMemChain = stUniteChainAccess.next.get( astMemChain );
	}
	return astObjMap;
}
static AST ccTypeGetObjMapArray( AST astType ){
	AST astObjMap;
	AST astMemType;
	AST astMemObj;
	U4  size;

	stObjectMapOfTypeAccess.alloc(1);
	astObjMap = stObjectMapOfTypeAccess.getMax();
	stObjectMapOfTypeAccess.type.set( astObjMap, astType );
	size = stTypeInfoAccess.size.get( astType );
	if( size == 0 ){
		stObjectMapOfTypeAccess.bAdjustable.set( astObjMap, TRUE );
	}else{
		stObjectMapOfTypeAccess.size.set( astObjMap, size );
	}
	astMemType = stTypeInfoAccess.elementType.get( astType );
	astMemObj = CcTypeGetObjMap(astMemType);
	stObjectMapOfTypeAccess.child.set( astObjMap, astMemObj );
	stObjectMapOfTypeAccess.parent.set( astMemObj, astObjMap );
	return astObjMap;
}
static AST ccTypeGetObjMapUnion( AST astType ){
	AST astObjMap;
	AST astMemChain;
	AST astSym;
	PSZ pszName;
	AST astMemType;
	AST astMemObj;
	AST astPreMem;

	stObjectMapOfTypeAccess.alloc(1);
	astObjMap = stObjectMapOfTypeAccess.getMax();
	stObjectMapOfTypeAccess.type.set( astObjMap, astType );

	astMemChain = stTypeInfoAccess.memChain.get( astType );
	astPreMem = 0;
	while( astMemChain > 0  ){
		astSym = stUniteChainAccess.parameter_sym.get( astMemChain );
		pszName = stSymbolInfoAccess.name.get( astSym );
		if( str_length( pszName ) == 0 ){
			astMemChain = stUniteChainAccess.next.get( astMemChain );
			continue;
		}
		astMemType = stSymbolInfoAccess.type.get( astSym );
		astMemObj = CcTypeGetObjMap(astMemType);
		stObjectMapOfTypeAccess.sym.set( astMemObj, astSym );
		if( astPreMem == 0 ){
			stObjectMapOfTypeAccess.child.set( astObjMap, astMemObj );
		}else{
			stObjectMapOfTypeAccess.sameObj.set( astPreMem, astMemObj );
		}
		stObjectMapOfTypeAccess.parent.set( astMemObj, astObjMap );
		astPreMem = astMemObj;
		astMemChain = stUniteChainAccess.next.get( astMemChain );
	}
	return astObjMap;
}
AST CcTypeGetObjMap( AST astType ){
	AST astObjMap;

	switch(stTypeInfoAccess.typeKind.get( astType )){
	case TYPEKIND_BASIC	:
	case TYPEKIND_POINTER:
	case TYPEKIND_ENUM:
	case TYPEKIND_BITFIELD:
		astObjMap = ccTypeGetObjMapSingle( astType );
		break;
	case TYPEKIND_ARRAY	:
		astObjMap = ccTypeGetObjMapArray( astType );
		break;
	case TYPEKIND_STRUCT:
		astObjMap = ccTypeGetObjMapStruct( astType );
		break;
	case TYPEKIND_UNION:
		astObjMap = ccTypeGetObjMapUnion( astType );
		break;
	default:
		astObjMap = 0;
		break;
	}
	return astObjMap;
}
U4 CcTypeGetTypeSize( AST astType ){
	U4  size;

	switch(stTypeInfoAccess.typeKind.get( astType )){
	case TYPEKIND_BASIC	:
	case TYPEKIND_POINTER:
	case TYPEKIND_ENUM:
	case TYPEKIND_BITFIELD:
	case TYPEKIND_STRUCT:
	case TYPEKIND_UNION:
		size = stTypeInfoAccess.size.get( astType );
		break;
	case TYPEKIND_ARRAY	:
		size = stTypeInfoAccess.size.get( astType );
		size *= CcTypeGetTypeSize( stTypeInfoAccess.elementType.get( astType ) );
		break;
	default:
		size = 0;
		break;
	}
	return size;
}
